home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-19 / iritsm3s.zip / XGLGRAPH.C < prev   
C/C++ Source or Header  |  1992-01-30  |  24KB  |  722 lines

  1. /*****************************************************************************
  2. *   General routines to    handle the graphic calls.                 *
  3. * currently supported devices:                             *
  4. * Input: Keyboard, mouse.                             *
  5. * Output: SGI 4D using gl library device.                     *
  6. *                                         *
  7. *    Note no transformation is using the hardware. All transformation is     *
  8. * performed in xviewobj module in software.                     *
  9. *                                         *
  10. * Written by:  Gershon Elber                Ver 0.1, Jul 1990.   *
  11. *****************************************************************************/
  12.  
  13. #include <gl/gl.h>
  14. #include <gl/device.h>
  15.  
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <math.h>
  19. #include <ctype.h>
  20. #include "irit_sm.h"
  21. #include "genmat.h"
  22. #include "graphgen.h"
  23.  
  24. /* Interactive menu setup structure: */
  25. #define INTERACT_NUM_OF_STRINGS        3
  26. #define INTERACT_NUM_OF_SUB_WNDWS_FULL 17
  27. #define INTERACT_NUM_OF_SUB_WNDWS_PART 14
  28.  
  29. typedef struct InteractString {
  30.     RealType X, Y;
  31.     int Color;
  32.     char *Str;
  33. } InteractString;
  34. typedef struct InteractSubWindow {
  35.     RealType X, Y;                       /* Center points. */
  36.     int Color;
  37.     GraphicEventType Event;
  38.     int TextInside; /* If TRUE, Str will be in window, otherwise left to it. */
  39.     char *Str;
  40. } InteractSubWindow;
  41. typedef struct InteractWindowStruct {     /* The interactive menu structures. */
  42.     /* Rotate, Translate, Scale strings: */
  43.     InteractString Strings[INTERACT_NUM_OF_STRINGS];
  44.     InteractSubWindow SubWindows[INTERACT_NUM_OF_SUB_WNDWS_FULL];
  45. } InteractWindowStruct;
  46.  
  47. #define INTERACT_SUB_WINDOW_WIDTH  0.8         /* Relative to window size. */
  48. #define INTERACT_SUB_WINDOW_HEIGHT 0.04
  49.  
  50. static int
  51.     InteractNumOfSubWndws = INTERACT_NUM_OF_SUB_WNDWS_FULL,
  52.     PopTransWndwAlways = TRUE,
  53.     TransWindowDisplayed = FALSE,
  54.     DoDoubleBuffer = TRUE;
  55.  
  56. /* Interactive mode menu set up structure is define below: */
  57. static InteractWindowStruct InteractMenuFull = {
  58.     { { 0.5, 0.81, RED,   "Rotate" },
  59.       { 0.5, 0.65, GREEN, "Translate" },
  60.       { 0.5, 0.49, CYAN,  "Scale" },
  61.     },
  62.     { { 0.5, 0.93, YELLOW, EVENT_SCR_OBJ_TGL,    TRUE,  "Screen Coords." },
  63.       { 0.5, 0.87, BLUE,   EVENT_PERS_ORTHO_TGL,TRUE,  "Perspective" },
  64.       { 0.5, 0.83, BLUE,   EVENT_PERS_ORTHO_Z,    FALSE, "Z" },
  65.       { 0.5, 0.75, RED,    EVENT_ROTATE_X,    FALSE, "X" }, /* Rot */
  66.       { 0.5, 0.71, RED,    EVENT_ROTATE_Y,    FALSE, "Y" },
  67.       { 0.5, 0.67, RED,    EVENT_ROTATE_Z,    FALSE, "Z" },
  68.       { 0.5, 0.59, GREEN,  EVENT_TRANSLATE_X,    FALSE, "X" }, /* Trans */
  69.       { 0.5, 0.55, GREEN,  EVENT_TRANSLATE_Y,    FALSE, "Y" },
  70.       { 0.5, 0.51, GREEN,  EVENT_TRANSLATE_Z,    FALSE, "Z" },
  71.       { 0.5, 0.43, CYAN,   EVENT_SCALE,        FALSE, "" },  /* Scale */
  72.       { 0.5, 0.35, MAGENTA,EVENT_DEPTH_CUE,    TRUE,  "Depth cue" },
  73.       { 0.5, 0.31, MAGENTA,EVENT_DRAW_SOLID,    TRUE,  "Wireframe" },
  74.       { 0.5, 0.25, YELLOW, EVENT_SAVE_GIF,    TRUE,  "Save GIF" },
  75.       { 0.5, 0.21, YELLOW, EVENT_SAVE_PS,    TRUE,  "Save PS" },
  76.       { 0.5, 0.15, YELLOW, EVENT_SAVE_MATRIX,    TRUE,  "Save Matrix" },
  77.       { 0.5, 0.11, YELLOW, EVENT_RESET_MATRIX,    TRUE,  "Reset Matrix" },
  78.       { 0.5, 0.03, WHITE,  EVENT_QUIT,        TRUE,  "Quit" },
  79.     }
  80. };
  81. static InteractWindowStruct InteractMenuPartial = {
  82.     { { 0.5, 0.77, RED,   "Rotate" },
  83.       { 0.5, 0.59, GREEN, "Translate" },
  84.       { 0.5, 0.41, CYAN,  "Scale" },
  85.     },
  86.     { { 0.5, 0.92, YELLOW, EVENT_SCR_OBJ_TGL,    TRUE,  "Screen Coords." },
  87.       { 0.5, 0.85, BLUE,   EVENT_PERS_ORTHO_TGL,TRUE,  "Perspective" },
  88.       { 0.5, 0.81, BLUE,   EVENT_PERS_ORTHO_Z,    FALSE, "Z" },
  89.       { 0.5, 0.71, RED,    EVENT_ROTATE_X,    FALSE, "X" }, /* Rot */
  90.       { 0.5, 0.67, RED,    EVENT_ROTATE_Y,    FALSE, "Y" },
  91.       { 0.5, 0.63, RED,    EVENT_ROTATE_Z,    FALSE, "Z" },
  92.       { 0.5, 0.53, GREEN,  EVENT_TRANSLATE_X,    FALSE, "X" }, /* Trans */
  93.       { 0.5, 0.49, GREEN,  EVENT_TRANSLATE_Y,    FALSE, "Y" },
  94.       { 0.5, 0.45, GREEN,  EVENT_TRANSLATE_Z,    FALSE, "Z" },
  95.       { 0.5, 0.35, CYAN,   EVENT_SCALE,        FALSE, "" },  /* Scale */
  96.       { 0.5, 0.27, MAGENTA,EVENT_DEPTH_CUE,    TRUE,  "Depth cue" },
  97.       { 0.5, 0.19, MAGENTA,EVENT_DRAW_SOLID,    TRUE,  "Wireframe" },
  98.       { 0.5, 0.11, YELLOW, EVENT_RESET_MATRIX,    TRUE,  "Reset Matrix" },
  99.       { 0.5, 0.03, WHITE,  EVENT_QUIT,        TRUE,  "Quit" },
  100.     }
  101. };
  102. static InteractWindowStruct *InteractMenu = &InteractMenuFull;
  103.  
  104. static short Colors[MAX_COLOR + 1][3] =
  105. {
  106.     { 0,   0,   0   },  /* 0. BLACK */
  107.     { 0,   0,   170 },  /* 1. BLUE */
  108.     { 0,   170, 0   },  /* 2. GREEN */
  109.     { 0,   170, 170 },  /* 3. CYAN */
  110.     { 170, 0,   0   },  /* 4. RED */
  111.     { 170, 0,   170 },  /* 5. MAGENTA */
  112.     { 170, 170, 0   },  /* 6. BROWN */
  113.     { 170, 170, 170 },  /* 7. LIGHTGREY */
  114.     { 85,  85,  85  },  /* 8. DARKGRAY */
  115.     { 85,  85,  255 },  /* 9. LIGHTBLUE */
  116.     { 85,  255, 85  },  /* 10. LIGHTGREEN */
  117.     { 85,  255, 255 },  /* 11. LIGHTCYAN */
  118.     { 255, 85,  85  },  /* 12. LIGHTRED */
  119.     { 255, 85,  255 },  /* 13. LIGHTMAGENTA */
  120.     { 255, 255, 85  },  /* 14. YELLOW */
  121.     { 255, 255, 255 }   /* 15. WHITE */
  122. };
  123.  
  124. static long
  125.     TransWinID = 0,
  126.     TransWinWidth = 100,
  127.     TransWinWidth2 = 50,
  128.     TransWinHeight = 100,
  129.     TransWinLow = 0,
  130.     TransWinLeft = 0,
  131.     ViewWinID = 0,
  132.     ViewWinWidth = 100,
  133.     ViewWinWidth2 = 50,
  134.     ViewWinHeight = 100,
  135.     ViewWinHeight2 = 50,
  136.     ViewWinLow = 0,
  137.     ViewWinLeft = 0;
  138.  
  139. static int
  140.     InGraphicMode = FALSE;
  141.  
  142. static Matrix
  143.     ViewStartMatrix;
  144.  
  145. static long GGMapX(RealType x);
  146. static long GGMapY(RealType y);
  147. static void SetTransformWindow(void);
  148. static void RedrawTransformWindow(void);
  149. static void SetViewWindow(void);
  150. static void DrawText(char *Str, long PosX, long PosY);
  151.  
  152. /****************************************************************************
  153. * Routine to map real -1..1 normalized coordinates to screen X size.        *
  154. ****************************************************************************/
  155. static long GGMapX(RealType x)
  156. {
  157.     return ViewWinWidth2 + ((long) (x * ViewWinWidth2));
  158. }
  159.  
  160. /****************************************************************************
  161. * Routine to map real -1..1 normalized coordinates to screen Y size.        *
  162. ****************************************************************************/
  163. static long GGMapY(RealType y)
  164. {
  165.     return ViewWinHeight2 + ((long) (y * ViewWinHeight2));
  166. }
  167.  
  168. /****************************************************************************
  169. * Routine to move to a normalized point    between    -1..1 on both axes :        *
  170. ****************************************************************************/
  171. void GGMyMove(RealType x, RealType y)
  172. {
  173.     move2i(GGMapX(x), GGMapY(y));
  174. }
  175.  
  176. /****************************************************************************
  177. * Routine to draw to a normalized point    between    -1..1 on both axes :        *
  178. ****************************************************************************/
  179. void GGMyDraw(RealType x, RealType y)
  180. {
  181.     draw2i(GGMapX(x), GGMapY(y));
  182. }
  183.  
  184. /****************************************************************************
  185. * Routine to draw a polygon full.                        *
  186. * Polygon is started by NewPoly = TRUE and Vertex == NULL, Normal == NULL.  *
  187. * Polygon is terminated NewPoly = FALSE and Vertex == NULL, Normal == NULL. *
  188. ****************************************************************************/
  189. void GGMyDrawPolygonSolid(double *Vertex, float *Normal, int NewPoly)
  190. {
  191.     if (Vertex == NULL && Normal == NULL) {
  192.     if (NewPoly)
  193.         bgnpolygon();
  194.     else
  195.         endpolygon();
  196.     }
  197.     else {
  198.     n3f(Normal);
  199.     v3d(Vertex);
  200.     }
  201. }
  202.  
  203. /****************************************************************************
  204. * Routine to set line style.                            *
  205. ****************************************************************************/
  206. void GGMySetLineStyle(int Style)
  207. {
  208.     setlinestyle((short) Style);
  209. }
  210.  
  211. /****************************************************************************
  212. * Routine to draw to a normelized point    between    -1..1 on both axes :        *
  213. ****************************************************************************/
  214. void GGMySetColor(int c)
  215. {
  216.     static float
  217.     Ambient = 0.25,
  218.     Diffuse = 0.75,
  219.     Specular = 1.0;
  220.     static float Material[] = {
  221.     AMBIENT,  0.25, 0.25, 0.25,
  222.     DIFFUSE,  0.75, 0.75, 0.75,
  223.     SPECULAR, 1.00, 1.00, 1.00,
  224.     SHININESS, 50,
  225.     LMNULL
  226.     };
  227.     static float Light1[] = {
  228.     AMBIENT, 0.25, 0.25, 0.25,
  229.     POSITION, 0.0, 0.0, 1.0, 0.0,
  230.     LMNULL
  231.     };
  232.     static float Light2[] = {
  233.     AMBIENT, 0.25, 0.25, 0.25,
  234.     POSITION, 0.0, 0.0, -1.0, 0.0,
  235.     LMNULL
  236.     };
  237.     int i;
  238.  
  239.     if (c < 0 || c > MAX_COLOR) c = WHITE;
  240.  
  241.     RGBcolor(Colors[c][0], Colors[c][1], Colors[c][2]);
  242.  
  243.     /* Prepare matrial structure in this color and select it. */
  244.     for (i = 0; i < 3; i++) {
  245.     Material[1 + i] = Ambient * Colors[c][i] / 255.0;
  246.     Material[5 + i] = Diffuse * Colors[c][i] / 255.0;
  247.     Material[9 + i] = Specular * Colors[c][i] / 255.0;
  248.     }
  249.     lmdef(DEFMATERIAL, 1, sizeof(Material) / sizeof(float), Material);
  250.     lmbind(MATERIAL, 1);
  251.     lmdef(DEFLIGHT, 1, sizeof(Light1) / sizeof(float), Light1);
  252.     lmbind(LIGHT1, 1);
  253.     lmdef(DEFLIGHT, 2, sizeof(Light2) / sizeof(float), Light2);
  254.     lmbind(LIGHT2, 2);
  255. }
  256.  
  257. /****************************************************************************
  258. * Routine to reset all the system to starting condition    :            *
  259. ****************************************************************************/
  260. void GGInitGraph(int argc, char **argv, int FullTransMode, int TransAlways)
  261. {
  262.     int i;
  263.  
  264.     if (InGraphicMode) return;
  265.  
  266.     if (FullTransMode) {
  267.         InteractNumOfSubWndws = INTERACT_NUM_OF_SUB_WNDWS_FULL;
  268.     InteractMenu = &InteractMenuFull;
  269.     DoDoubleBuffer = TRUE;
  270.     }
  271.     else {
  272.         InteractNumOfSubWndws = INTERACT_NUM_OF_SUB_WNDWS_PART;
  273.     InteractMenu = &InteractMenuPartial;
  274.     DoDoubleBuffer = FALSE;
  275.     }
  276.  
  277.     PopTransWndwAlways = TransAlways;
  278.  
  279.     SetViewWindow();
  280.  
  281.     qdevice(LEFTMOUSE);
  282.     qdevice(MIDDLEMOUSE);
  283.     qdevice(RIGHTMOUSE);
  284.  
  285.     /* The default drawing window is the view window. */
  286.     winset(ViewWinID);
  287.  
  288.     deflinestyle((short) DOTTED_LINE, (Linestyle) 0x3333);
  289.     setbell(1);                           /* Make it short. */
  290.  
  291.     InGraphicMode = TRUE;
  292. }
  293.  
  294. /****************************************************************************
  295. * Routine to close and shutdown    graphic    mode :                    *
  296. ****************************************************************************/
  297. void GGCloseGraph(void)
  298. {
  299.     if (!InGraphicMode) return;
  300.  
  301.     InGraphicMode = FALSE;
  302. }
  303.  
  304. /*****************************************************************************
  305. * Routine to print a message on the given location:                 *
  306. *****************************************************************************/
  307. void GGPutMsgXY(char *s, RealType x, RealType y)
  308. {
  309.     int Width = strwidth(s);
  310.  
  311.     move2s((short) (GGMapX(x) - Width / 2),
  312.        (short) (GGMapY(y) - getheight() / 2));
  313.     charstr(s);
  314. }
  315.  
  316. /*****************************************************************************
  317. *   Routine to clear the viewing area.                         *
  318. *****************************************************************************/
  319. void GGClearViewArea(void)
  320. {
  321.     static Matrix
  322.     IDMat = { 1.0, 0.0, 0.0, 0.0,
  323.           0.0, 1.0, 0.0, 0.0,
  324.           0.0, 0.0, 1.0, 0.0,
  325.           0.0, 0.0, 0.0, 1.0 };
  326.  
  327.     GGMySetColor(BLACK);
  328.     clear();
  329.  
  330.     if (winget() == ViewWinID) {
  331.     /* activate zbuffer only if we are in solid drawing mode. */
  332.     if (GlblDrawSolid) {
  333.         mmode(MVIEWING);
  334.         ortho(-1.0, 1.0, -1.0, 1.0, -2.0, 2.0);
  335.         loadmatrix(IDMat);
  336.  
  337.         /* Define necessary staff for Lighting. */
  338.         lmbind(MATERIAL, 1);
  339.         lmbind(LIGHT1, 1);
  340.         lmbind(LIGHT2, 2);
  341.         lmbind(LMODEL, 1);
  342.  
  343.         zbuffer(TRUE);
  344.         zclear();
  345.     }
  346.     else {
  347.         mmode(MSINGLE);
  348.         loadmatrix(ViewStartMatrix);
  349.  
  350.         zbuffer(FALSE);
  351.     }
  352.     }
  353. }
  354.  
  355. /*****************************************************************************
  356. * Routine to make some sound with given Frequency, Time milliseconds:         *
  357. *****************************************************************************/
  358. void GGTone(int Frequency, int Duration)
  359. {
  360.     if (GlblDoGraphics)
  361.     ringbell();
  362. }
  363.  
  364. /*****************************************************************************
  365. * Set up and draw a transformation window.                     *
  366. *****************************************************************************/
  367. static void SetTransformWindow(void)
  368. {
  369.     long PrefPos[4];
  370.  
  371. #ifndef _AIX
  372.     foreground();
  373. #endif
  374.  
  375.     if (sscanf(GlblTransPrefPos, "%ld, %ld, %ld, %ld",
  376.            &PrefPos[0], &PrefPos[1], &PrefPos[2], &PrefPos[3]) == 4)
  377.     prefposition(PrefPos[0], PrefPos[1], PrefPos[2], PrefPos[3]);
  378.     else if (sscanf(GlblTransPrefPos, "%ld, %ld",
  379.             &PrefPos[0], &PrefPos[1]) == 2)
  380.     prefsize(PrefPos[0], PrefPos[1]);
  381.     winopen("Poly3dTrans");
  382.     if (DoDoubleBuffer) doublebuffer();
  383.     RGBmode();
  384.     gconfig();
  385.     getorigin(&TransWinLeft, &TransWinLow);
  386.     getsize(&TransWinWidth, &TransWinHeight);
  387.     TransWinWidth2 = TransWinWidth / 2;
  388.     TransWinID = winget();
  389.  
  390.     GGMySetColor(BLACK);
  391.     clear();
  392.     if (DoDoubleBuffer) swapbuffers();
  393.  
  394.     /* This is wierd. without the sleep the gl get mixed up between the two  */
  395.     /* windows. If you have any idea why, let me know...             */
  396.     sleep(1);
  397. }
  398.  
  399. /*****************************************************************************
  400. * Set up and draw a transformation window.                     *
  401. *****************************************************************************/
  402. static void RedrawTransformWindow(void)
  403. {
  404.     int i;
  405.     long SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight;
  406.  
  407.     /* Make sure the menu is consistent with internatal data. */
  408.     InteractMenu -> SubWindows[0].Str =
  409.     GlblTransformMode == TRANS_OBJECT ? "Object Coords." : "Screen Coords.";
  410.     InteractMenu -> SubWindows[1].Str =
  411.     GlblViewMode == VIEW_PERSPECTIVE ? "Perspective" : "Orthographic";
  412.     InteractMenu -> SubWindows[10].Str =
  413.     GlblDepthCue ? "Depth cue" : "No depth cue";
  414.     InteractMenu -> SubWindows[11].Str =
  415.     GlblDrawSolid ? "Solid" : "Wireframe";
  416.  
  417.     winset(TransWinID);                /* Draw in the transformation window. */
  418.  
  419.     SubTransWidth = (int) (TransWinWidth * INTERACT_SUB_WINDOW_WIDTH);
  420.     SubTransHeight = (int) (TransWinHeight * INTERACT_SUB_WINDOW_HEIGHT);
  421.     SubTransPosX = (TransWinWidth - SubTransWidth) / 2;
  422.  
  423.     GGMySetColor(BLACK);
  424.     clear();
  425.  
  426.     for (i = 0; i < InteractNumOfSubWndws; i++) {
  427.     GGMySetColor(InteractMenu -> SubWindows[i].Color);
  428.     SubTransPosY = (int) (TransWinHeight * InteractMenu -> SubWindows[i].Y);
  429.  
  430.     move2i(SubTransPosX, SubTransPosY);
  431.     draw2i(SubTransPosX + SubTransWidth, SubTransPosY);
  432.     draw2i(SubTransPosX + SubTransWidth, SubTransPosY + SubTransHeight);
  433.     draw2i(SubTransPosX, SubTransPosY + SubTransHeight);
  434.     draw2i(SubTransPosX, SubTransPosY);
  435.     if (InteractMenu -> SubWindows[i].TextInside) {
  436.         DrawText(InteractMenu -> SubWindows[i].Str,
  437.              TransWinWidth / 2,
  438.              SubTransPosY + SubTransHeight / 2);
  439.     }
  440.     else {
  441.         DrawText(InteractMenu -> SubWindows[i].Str,
  442.              (TransWinWidth - SubTransWidth) / 3,
  443.              SubTransPosY + SubTransHeight / 2);
  444.         move2i(SubTransPosX + SubTransWidth / 2, SubTransPosY);
  445.         draw2i(SubTransPosX + SubTransWidth / 2,
  446.            SubTransPosY + SubTransHeight);
  447.     }
  448.     }
  449.  
  450.     for (i = 0; i < INTERACT_NUM_OF_STRINGS; i++) {
  451.     GGMySetColor(InteractMenu -> Strings[i].Color);
  452.     DrawText(InteractMenu -> Strings[i].Str,
  453.          (int) (InteractMenu -> Strings[i].X * TransWinWidth),
  454.          (int) (InteractMenu -> Strings[i].Y * TransWinHeight));
  455.     }
  456.  
  457.     if (DoDoubleBuffer) swapbuffers();
  458.  
  459.     winset(ViewWinID);             /* Go back to the default drawing window. */
  460. }
  461.  
  462. /*****************************************************************************
  463. * Set up and draw a view window.                             *
  464. *****************************************************************************/
  465. static void SetViewWindow(void)
  466. {
  467.     long PrefPos[4];
  468.  
  469. #ifndef _AIX
  470.     foreground();
  471. #endif
  472.  
  473.     if (sscanf(GlblViewPrefPos, "%ld, %ld, %ld, %ld",
  474.            &PrefPos[0], &PrefPos[1], &PrefPos[2], &PrefPos[3]) == 4)
  475.     prefposition(PrefPos[0], PrefPos[1], PrefPos[2], PrefPos[3]);
  476.     else if (sscanf(GlblViewPrefPos, "%ld, %ld",
  477.             &PrefPos[0], &PrefPos[1]) == 2)
  478.     prefsize(PrefPos[0], PrefPos[1]);
  479.     winopen("Poly3dView");
  480.     if (DoDoubleBuffer) doublebuffer();
  481.     RGBmode();
  482.     gconfig();
  483.     getorigin(&ViewWinLeft, &ViewWinLow);
  484.     getsize(&ViewWinWidth, &ViewWinHeight);
  485.     ViewWinWidth2 = ViewWinWidth / 2;
  486.     ViewWinHeight2 = ViewWinHeight / 2;
  487.     
  488.     getmatrix(ViewStartMatrix);
  489.     ViewWinID = winget();
  490.  
  491.     GGClearViewArea();
  492.     if (DoDoubleBuffer) swapbuffers();
  493.  
  494.     concave(TRUE);
  495.  
  496.     /* Define necessary staff for Lighting. */
  497.     lmdef(DEFMATERIAL, 1, 0, NULL);
  498.     lmdef(DEFLIGHT, 1, 0, NULL);
  499.     lmdef(DEFLMODEL, 1, 0, NULL);
  500.  
  501.     /* This is wierd. without the sleep the gl get mixed up between the two  */
  502.     /* windows. If you have any idea why, let me know...             */
  503.     sleep(1);
  504. }
  505.  
  506. /*****************************************************************************
  507. * Return View window ID.                             *
  508. *****************************************************************************/
  509. long GetViewWindowID()
  510. {
  511.     return ViewWinID;
  512. }
  513.  
  514. /******************************************************************************
  515. * Returns status of abort key if pressed, and reset it.                  *
  516. ******************************************************************************/
  517. int GGIsAbortKeyPressed(void)
  518. {
  519.     return getbutton(RIGHTMOUSE) == 1;
  520. }
  521.  
  522. /******************************************************************************
  523. * Handle gl events                                  *
  524. ******************************************************************************/
  525. GraphicEventType GGGetGraphicEvent(RealType *ChangeFactor)
  526. {
  527.     static GraphicEventType
  528.     LastEvent = EVENT_NONE;
  529.     static long
  530.     LastX = -1;
  531.     int i,
  532.         LeftButtonIsPressed = getbutton(LEFTMOUSE) == 1;
  533.     GraphicEventType
  534.     RetVal = EVENT_NONE;
  535.     short data;
  536.     long x, y, dev;
  537.     RealType XPos, YPos;
  538.  
  539.     if (!TransWindowDisplayed) {
  540.     /* Pop up the transformation window. */
  541.     SetTransformWindow();
  542.     RedrawTransformWindow();
  543.     TransWindowDisplayed = TRUE;
  544.     }
  545.  
  546.     if (GlblWasCtrlBrk) {
  547.     GlblWasCtrlBrk = FALSE;
  548.  
  549.     if (!PopTransWndwAlways) {
  550.         winclose(TransWinID);
  551.         TransWindowDisplayed = FALSE;
  552.     }
  553.  
  554.     return EVENT_QUIT;
  555.     }
  556.  
  557.     /* Allow continuous drag on following events only: */
  558.     if (LeftButtonIsPressed &&
  559.     !(LastEvent == EVENT_PERS_ORTHO_Z ||
  560.       LastEvent == EVENT_ROTATE_X ||
  561.       LastEvent == EVENT_ROTATE_Y ||
  562.       LastEvent == EVENT_ROTATE_Z ||
  563.       LastEvent == EVENT_TRANSLATE_X ||
  564.       LastEvent == EVENT_TRANSLATE_Y ||
  565.       LastEvent == EVENT_TRANSLATE_Z ||
  566.       LastEvent == EVENT_SCALE)) {
  567.     while (getbutton(LEFTMOUSE) == 1);
  568.     LeftButtonIsPressed = FALSE;
  569.     }
  570.  
  571.     if (LeftButtonIsPressed) {
  572.     /* Allow leaving the Trans window if still pressed, and use last     */
  573.     /* event as the returned event.    Note we wait until current position  */
  574.     /* is different from last one to make sure we do something.          */
  575.     while((x = getvaluator(MOUSEX) - TransWinLeft) == LastX &&
  576.           getbutton(LEFTMOUSE) == 1);
  577.     if (x != LastX) {
  578.         *ChangeFactor = (((RealType) x) - LastX) / TransWinWidth2;
  579.         LastX = x;
  580.         return LastEvent;
  581.     }
  582.     else
  583.         LeftButtonIsPressed = FALSE;
  584.     }
  585.  
  586.     LastEvent = EVENT_NONE;
  587.  
  588.     while (RetVal == EVENT_NONE) {
  589.     /* Wait for left button to be pressed in the Trans window. Note this */
  590.     /* is the loop we are going to cycle in idle time.             */
  591.     while (getbutton(LEFTMOUSE) != 1 ||
  592.            (x = getvaluator(MOUSEX)) < TransWinLeft ||
  593.            x > TransWinLeft + TransWinWidth ||
  594.            (y = getvaluator(MOUSEY)) < TransWinLow ||
  595.            y > TransWinLow + TransWinHeight) {
  596.         if (GlblWasCtrlBrk) {
  597.         GlblWasCtrlBrk = FALSE;
  598.  
  599.         if (!PopTransWndwAlways) {
  600.             winclose(TransWinID);
  601.             TransWindowDisplayed = FALSE;
  602.         }
  603.  
  604.         return EVENT_QUIT;
  605.         }
  606.  
  607.         if (qtest()) {                  /* Any external event occured? */
  608.         switch (dev = qread(&data)) {
  609.             case REDRAW:
  610.             if (data == ViewWinID) {
  611.                 getorigin(&ViewWinLeft, &ViewWinLow);
  612.                 getsize(&ViewWinWidth, &ViewWinHeight);
  613.                 ViewWinWidth2 = ViewWinWidth / 2;
  614.                 ViewWinHeight2 = ViewWinHeight / 2;
  615.                 reshapeviewport();
  616.                 ortho2(-0.5, ViewWinWidth - 0.5,
  617.                    -0.5, ViewWinHeight - 0.5);
  618.                 getmatrix(ViewStartMatrix);
  619.                 UpdateInteractHandleInput();
  620.             }
  621.             else if (data == TransWinID) {
  622.                 winset(TransWinID);
  623.                 getorigin(&TransWinLeft, &TransWinLow);
  624.                 getsize(&TransWinWidth, &TransWinHeight);
  625.                 reshapeviewport();
  626.                 ortho2(-0.5, TransWinWidth - 0.5,
  627.                    -0.5, TransWinHeight - 0.5);
  628.                 TransWinWidth2 = TransWinWidth / 2;
  629.                 RedrawTransformWindow();
  630.                 winset(ViewWinID);
  631.             }
  632.             break;
  633.         }
  634.         }
  635.     }
  636.  
  637.     x -= TransWinLeft;
  638.     y -= TransWinLow;
  639.  
  640.     XPos = ((RealType) x) / TransWinWidth;
  641.     YPos = ((RealType) y) / TransWinHeight;
  642.  
  643.     /* Make sure we are in bound in the X direction. */
  644.     if (XPos < (1.0 - INTERACT_SUB_WINDOW_WIDTH) / 2.0 ||
  645.         XPos > 1.0 - (1.0 - INTERACT_SUB_WINDOW_WIDTH) / 2.0) {
  646.         GGTone(1000, 100);
  647.         continue;
  648.     }
  649.  
  650.     /* Now search the sub window the event occured in. */
  651.     for (i = 0; i < InteractNumOfSubWndws; i++) {
  652.         if (InteractMenu -> SubWindows[i].Y <= YPos &&
  653.         InteractMenu -> SubWindows[i].Y + INTERACT_SUB_WINDOW_HEIGHT >=
  654.                                     YPos) {
  655.         RetVal = InteractMenu -> SubWindows[i].Event;
  656.         break;
  657.         }
  658.     }
  659.     if (i == InteractNumOfSubWndws) {
  660.         GGTone(1000, 100);
  661.         continue;
  662.     }
  663.  
  664.     /* Take care of special cases in which the window should be updated. */
  665.     switch (RetVal) {
  666.         case EVENT_SCR_OBJ_TGL:
  667.         GlblTransformMode = GlblTransformMode == TRANS_OBJECT ?
  668.                              TRANS_SCREEN :
  669.                              TRANS_OBJECT;
  670.         RedrawTransformWindow();
  671.         break;
  672.         case EVENT_PERS_ORTHO_TGL:
  673.             GlblViewMode = GlblViewMode == VIEW_PERSPECTIVE ?
  674.                            VIEW_ORTHOGRAPHIC :
  675.                            VIEW_PERSPECTIVE;
  676.         RedrawTransformWindow();
  677.         break;
  678.         case EVENT_DEPTH_CUE:
  679.             GlblDepthCue = !GlblDepthCue;
  680.         RedrawTransformWindow();
  681.         break;
  682.         case EVENT_DRAW_SOLID:
  683.             GlblDrawSolid = !GlblDrawSolid;
  684.         RedrawTransformWindow();
  685.         break;
  686.         case EVENT_QUIT:
  687.         if (!PopTransWndwAlways) {
  688.             winclose(TransWinID);
  689.             TransWindowDisplayed = FALSE;
  690.         }
  691.         break;
  692.     }
  693.  
  694.     *ChangeFactor = (((RealType) x) - TransWinWidth2) / TransWinWidth2;
  695.     }
  696.  
  697.     LastEvent = RetVal;
  698.     LastX = x;
  699.  
  700.     return RetVal;
  701. }
  702.  
  703. /******************************************************************************
  704. * Flush output of graphic command.                          *
  705. ******************************************************************************/
  706. void GGGraphicFlush(void)
  707. {
  708.     /* We are using double buffering - flip buffers. */
  709.     if (DoDoubleBuffer) swapbuffers();
  710. }
  711.  
  712. /******************************************************************************
  713. * Draw text centered at the given position.                      *
  714. ******************************************************************************/
  715. static void DrawText(char *Str, long PosX, long PosY)
  716. {
  717.     long Width = strwidth(Str);
  718.  
  719.     cmov2s(PosX - Width / 2, PosY - (getheight() / 2 - getdescender()));
  720.     charstr(Str);
  721. }
  722.